/***************************************************************************
*   Copyright (C) 2009 by Steven Waslander   *
*   stevenw@uwaterloo.ca   *
*                                                                         *
***************************************************************************/

#ifndef _VEC_H
#define _VEC_H

#include <cassert>
#include "Matrix.h"

static const bool vecDebug = true;

template <class T> 
class Vec : public Matrix<T>{
  public:
    // Constructors
    Vec(int length = 3);
    Vec(const Vec& src);
    
    // Accessors
    inline T& operator() (int i); // get and set 
    inline T& operator() (int i) const; // get only for const correctness
    inline T& operator[] (int i) ;
    inline T& operator[] (int i) const; // get only for const correctness
    Vec<T>& operator= (const Vec<T>& src) ;
    Vec<T> operator+ (const Vec<T>& rhs) ;
    Vec<T> operator- (const Vec<T>& rhs) ;
    Vec<T> operator* (const double rhs) ;
    
  protected:
    using Matrix<T>::rows;
    using Matrix<T>::cols;
    using Matrix<T>::data;
};

//! Initializes without setting data values to anything, to ease allocation overhead
template <class T>
Vec<T>::Vec(int _length) : Matrix<T>(_length, 1) 
{
}

//! Copy constructor
template <class T>
Vec<T>::Vec(const Vec<T>& src)
{
  rows = src.rows;
  cols = 1;
  data = new T[rows];

  for (int i=0; i<rows; i++) {
    (*this)(i) = src(i);
  }
}

template <class T>
inline T& Vec<T>::operator() (int i) // get and set 
{
  if (vecDebug) assert(i>=0 && i<rows);
  return data[i];
}

template <class T>
inline T& Vec<T>::operator[] (int i) // get and set 
{
  return operator()(i) ;  
}

template <class T>
inline T& Vec<T>::operator() (int i) const // get only for const correctness
{
  if (vecDebug) assert(i>=0 && i<rows);
  return data[i];
}

template <class T>
inline T& Vec<T>::operator[] (int i) const // get only for const correctness
{
  return operator()(i) ;
}

template <class T>
Vec<T>& Vec<T>::operator= (const Vec<T>& src)
{
  if (this != &src)
  {
    for (int i=0;i<src.rows;i++)
    {
        (*this)(i) = src(i);
    }
  }
  return *this;
}

template <class T>
Vec<T> Vec<T>::operator+ (const Vec<T>& rhs)
{
  Vec<T> result(rhs) ;
  
  assert(rhs.NumRows() == this->NumRows()) ;
  
  for (int i=0; i<rhs.rows; i++)
  {
    result(i) = (*this)(i) + rhs(i) ;
  }
  return result ;
}

template <class T>
Vec<T> Vec<T>::operator- (const Vec<T>& rhs)
{
  Vec<T> result(rhs) ;
  
  assert(rhs.NumRows() == this->NumRows()) ;
  
  for (int i=0; i<rhs.rows; i++)
  {
    result(i) = (*this)(i) - rhs(i) ;
  }
  return result ;
}

template <class T>
Vec<T> Vec<T>::operator* (const double rhs)
{
  Vec<T> result(*this) ;
  for (int i=0; i < rows; i++)
  {
    result(i) = result(i)*rhs ;
  }
  return result ;
}

#endif // _VEC_H
